package listutil

import (
	"fmt"
	"reflect"
)

// getNumericValue returns the numeric value of a field as float64.
func getNumericValue(v reflect.Value) (float64, error) {
	// 如果v是interface{}类型，获取其实际持有的值
	if v.Kind() == reflect.Interface && !v.IsNil() {
		v = v.Elem()
	}

	switch v.Kind() {
	case reflect.Int, reflect.Int32, reflect.Int64:
		return float64(v.Int()), nil
	case reflect.Uint, reflect.Uint32, reflect.Uint64:
		return float64(v.Uint()), nil
	case reflect.Float32, reflect.Float64:
		return v.Float(), nil
	default:
		return 0, fmt.Errorf("unsupported type: %v", v.Type())
	}
}

// DeduplicateAndKeepMaxReflect 根据字段a去重，保留字段b的最大值
func DeduplicateAndKeepMaxReflect[T any](items []T, aField, bField string) ([]T, error) {
	uniqueItems := make(map[interface{}]T)

	for _, item := range items {
		itemValue := reflect.ValueOf(item)

		// 如果item是指针，获取其指向的值
		if itemValue.Kind() == reflect.Ptr && !itemValue.IsNil() {
			itemValue = itemValue.Elem()
		}

		aValue := itemValue.FieldByName(aField).Interface()

		// 检查是否存在
		if existingItem, ok := uniqueItems[aValue]; ok {
			bValue, err := getNumericValue(itemValue.FieldByName(bField))
			if err != nil {
				return nil, err
			}
			existingItemValue := reflect.ValueOf(existingItem)
			// 如果existingItem是指针，获取其指向的值
			if existingItemValue.Kind() == reflect.Ptr && !existingItemValue.IsNil() {
				existingItemValue = existingItemValue.Elem()
			}
			existingBValue, err := getNumericValue(existingItemValue.FieldByName(bField))
			if err != nil {
				return nil, err
			}

			if bValue > existingBValue {
				uniqueItems[aValue] = item
			}
		} else {
			uniqueItems[aValue] = item
		}
	}

	var result []T
	for _, item := range uniqueItems {
		result = append(result, item)
	}

	return result, nil
}
